////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_CORE_MACROS_H__
#define __WN_CORE_MACROS_H__

#include "WNCore/inc/WNPlatform.h"
#include "WNCore/inc/WNTypes.h"

#ifdef _WN_WINDOWS
    #include <windows.h>
#elif defined _WN_LINUX
    #include <signal.h>
#endif

#include <stdio.h>
#include <limits.h>

#ifdef _WN_MSVC
    #define WN_UNUSED_ARG(_argument) (_argument)
    #define WN_SNPRINTF _snprintf
#else
    #define WN_UNUSED_ARG(_argument) (static_cast<WN_VOID>(sizeof((_argument), 0)))
    #define WN_SNPRINTF snprintf
#endif

#ifdef _WN_DEBUG
    #ifdef _WN_LINUX
        #define WN_DEBUG_BREAK() raise(SIGTRAP)
    #else
        #ifdef _WN_MSVC
            #define WN_DEBUG_BREAK() __debugbreak()
        #elif defined _WN_GNUC || defined _WN_CLANG
            #ifdef _WN_X86
                WN_DEBUG_BREAK() __asm__ __volatile__ ("int $3")
            #else
                WN_DEBUG_BREAK()
            #endif
        #endif
    #endif
#else
    #define WN_DEBUG_BREAK()
#endif

#ifdef _WN_WINDOWS
    #define WN_YIELD_PROCESSOR() _mm_pause()
#else
    #if defined _WN_GNUC || defined _WN_CLANG
        #ifdef _WN_X86
            #define WN_YIELD_PROCESSOR() __asm__ __volatile__ ("rep; nop" : : : "memory")
        #endif
    #endif
#endif

#define WN_BITS_PER_BYTE CHAR_BIT

#define WN_KILOBYTES_TO_BYTES(_value) (1024 * (_value))
#define WN_MEGABYTES_TO_BYTES(_value) (1024 * WN_KILOBYTES_TO_BYTES(_value))
#define WN_GIGABYTES_TO_BYTES(_value) (1024 * WN_MEGABYTES_TO_BYTES(_value))

#define WN_BYTES_TO_BITS(_value) (WN_BITS_PER_BYTE * (_value))

#define WN_ARRAY_LENGTH(_array) (sizeof(_array) / sizeof(_array[0]))

#define WN_STRINGERIZE(_value) #_value

#define WN_PRINTF printf
#define WN_SPRINTF sprintf
#define WN_WSPRINTF wsprintf

#define WN_BIT_MASK(_bit) (1LL << (_bit))
#define WN_BIT_SET(_value, _bit) ((_value) |= WN_BIT_MASK(_bit))
#define WN_BIT_CLEAR(_value, _bit) ((_value) &= ~WN_BIT_MASK(_bit))
#define WN_BIT_FLIP(_value, _bit) ((_value) ^= WN_BIT_MASK(_bit))
#define WN_BIT_TEST(_value, _bit) (((_value) & WN_BIT_MASK(_bit)) != 0)

#define __WN_UNIQUE_VARIABLE_MERGE(_prefix, _line, _counter)  _prefix##_##_line##_##_counter
#define __WN_UNIQUE_VARIABLE_PASSTHROUGH(_prefix, _line, _counter) __WN_UNIQUE_VARIABLE_MERGE(_prefix, _line, _counter)
#define WN_UNIQUE_VARIABLE(_prefix) __WN_UNIQUE_VARIABLE_PASSTHROUGH(_prefix, __LINE__, __COUNTER__)

#endif // __WN_CORE_MACROS_H__
